import {defineStore} from 'pinia';
import {Socket} from "socket.io-client/build/esm/socket";
import {io} from "socket.io-client";
import {useUserStore} from "@/store/modules/user";
import {getChatMessageList, getOnlineUserList, getChatRooms} from "@/api/worker/imchat";

export type IImChatState = {
  socket: Socket | null,
  chatRoomList: Array<object>,
  currentRoom: object,
  messageList: Array<object>,
  messageCursor: string | null,
  messageHasNext: boolean,
  userOnlineList: Array<object>,
};

export enum EventEnum {
  CONN = 'connect',
  MESSAGE = 'message',
  USER_ONLINE = 'userOnline',
  DIS_CONN = 'disconnect'
}

export const useImChatStore = defineStore({
  id: 'app-imchat',
  state: (): IImChatState => ({
    socket: null,
    chatRoomList: [],
    currentRoom: {},
    messageList: [],
    messageCursor: null,
    messageHasNext: true,
    userOnlineList: []
  }),
  getters: {
    getSocket(): Socket {
      // @ts-ignore
      return this.socket;
    },
    getChatRoomList(): Array<object> {
      return this.chatRoomList;
    },
    getCurrentRoom(): object {
      return this.currentRoom;
    },
    getMessageList(): Array<object> {
      return this.messageList;
    },
    getLastMessage(): object | null {
      return this.messageList.length ? this.messageList[this.messageList.length-1] : null
    },
  },
  actions: {
    initSocket() {
      if (this.socket === null) {
        const { getToken } = useUserStore()
        this.socket = io({
          path: '/socket',
          query: {
            token: getToken
          },
          // 重连次数
          reconnectionAttempts: 20
        });
        this.subEvent(EventEnum.CONN, () => console.log('连接事件'));
        this.subEvent(EventEnum.MESSAGE, result => {
          console.log('消息事件', result)
          if (result?.data) {
            this.messageList.push(result.data)
          } else {
            window['$message'].warning(result.message)
          }
        });
        this.subEvent(EventEnum.USER_ONLINE, result => {
          console.log('用户上下线事件');
          if (result?.data) {
            // 上线
            for (let i = 0; i < this.userOnlineList.length; i++) {
              let userInfo = this.userOnlineList[i];
              // @ts-ignore
              if (userInfo.username === result.data.username) {
                return;
              }
            }
            this.userOnlineList.unshift({
              username: result.data.username,
              avatar: result.data.avatar
            })
          } else {
            // 下线
            for (let i = 0; i < this.userOnlineList.length; i++) {
              let userInfo = this.userOnlineList[i];
              // @ts-ignore
              if (userInfo.username === result.message) {
                this.userOnlineList.splice(i, 1);
                return;
              }
            }
          }
        });
        this.subEvent(EventEnum.DIS_CONN, result => {
          console.log('销毁事件', result)
          if (result === 'io server disconnect') {
            const $dialog = window['$dialog'];
            $dialog.warning({
              title: '警告',
              content: '管理员强制下线',
              positiveText: '确定',
              closable: false,
              maskClosable: false,
              onPositiveClick: async () => {
                const { logout } = useUserStore()
                await logout();
              },
              onNegativeClick: () => {},
            });
          }
        });
      }
    },
    socketClose() {
      if (this.socket != null) {
        this.socket.close();
        this.socket = null;
      }
    },
    /** 订阅事件 */
    subEvent(eventName: string, args) {
      if (this.socket !== null) {
        this.socket.on(eventName, args)
      }
    },
    /** 取消事件 **/
    offEvent(eventName: string, args) {
      if (this.socket !== null) {
        this.socket.off(eventName, args)
      }
    },
    /** 触发事件 **/
    emitEvent(eventName: string, args) {
      if (this.socket !== null) {
        this.socket.emit(eventName, args)
      }
    },
    async loadMessageList(pageSize: number = 10): Promise<number> {
      if (this.messageHasNext) {
        // @ts-ignore
        const { records, size, hasNext, cursor } = await getChatMessageList({
          cursor: this.messageCursor,
          size: pageSize
        })
        this.messageList.unshift(...records);
        this.messageCursor = cursor
        this.messageHasNext = hasNext
        return Promise.resolve(size)
      }
      return Promise.resolve(0)
    },
    async loadUserOnlineList() {
      this.userOnlineList = await getOnlineUserList();
      // @ts-ignore
      const { username, avatar } = useUserStore().getUserInfo;
      if (this.userOnlineList.length === 0) {
        this.userOnlineList.push({
          username, avatar
        })
      }
    },
    async loadChatRoomList() {
      this.chatRoomList = await getChatRooms();
      this.currentRoom = this.chatRoomList[0];
    },
    /** socket相关的启动器 **/
    async bootstrapSocket() {
      await this.initSocket();
      await this.loadChatRoomList();
      await this.loadMessageList();
      await this.loadUserOnlineList();
    }
  },
});
